#include "shellinvoker.h"
#include <QDebug>
#include <QProcess>

ShellInvoker::ShellInvoker(){
   m_reRunning=false;
   innerProcess = new QProcess(this);
   innerProcess->setProcessChannelMode(QProcess::MergedChannels);
   connect(innerProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(readyToRead()));
   connect(innerProcess,SIGNAL(readyReadStandardError()),this,SLOT(readyToReadError()));
   connect(innerProcess,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(processFinished(int, QProcess::ExitStatus)));
}

ShellInvoker::~ShellInvoker()
{
}

void ShellInvoker::setWaitFor(QString waitFor){
    m_waitFor=waitFor;
}
void ShellInvoker::setWorkingDir(QString wDir){
    innerProcess->setWorkingDirectory(wDir);
}

void ShellInvoker::shellWholeAction(QString command){
    QStringList * arg = new QStringList;
    this->shellAction(command,*arg);
}

void ShellInvoker::shellAction(QString str,QStringList sArg){
    m_cmd=str;
    m_sArg=sArg;
    if(QProcess::NotRunning == innerProcess->state()){
        qDebug() << "run now";
        this->startProcess();
        return;
    }
    qDebug() << "stop and run";
    m_reRunning=true;
    this->kill();
}

void ShellInvoker::startProcess() {

    qDebug() << "exec action: " << m_cmd;
    //qDebug() << "m_waitFor: " << m_waitFor;
    qDebug() << "sArg: " << m_sArg;

    if(m_sArg.length()==0)innerProcess->start(m_cmd);
    else innerProcess->start(m_cmd,m_sArg);
    //qDebug() << "before launched";
        if ((m_waitFor=="start") && !innerProcess->waitForStarted(-1))
            qDebug() << "Start failed:" << innerProcess->errorString();
        else if ((m_waitFor=="finish") && !innerProcess->waitForFinished(-1 ) )
            qDebug() << "Finished failed:" << innerProcess->errorString();
        else {
            m_outputLine = innerProcess->readAll();
            qDebug() << "out:" << m_outputLine;
            qDebug() << "err:" << innerProcess->readAllStandardError();
        }
    //qDebug() << "launched";
    emit(launched());
}

void ShellInvoker::kill(){
    innerProcess->kill();
}

QString ShellInvoker::outputLine() const {
    return m_outputLine;
}

int ShellInvoker::processState() const {
    return innerProcess->state();
}

void ShellInvoker::readyToRead() {
    while(innerProcess->canReadLine()) {
        m_outputLine = innerProcess->readLine().trimmed();
        //QByteArray buffer();
        //qDebug() << "readLine" << m_outputLine;
        emit(outputLineChanged());
    }



}

void ShellInvoker::processFinished(int exitCode, QProcess::ExitStatus exitStatus){
    if(m_reRunning){
        startProcess();
        m_reRunning=false;
        return;
    }
    emit(finished(exitCode));
}

void ShellInvoker::readyToReadError() {
    m_outputLine = QString(innerProcess->readAllStandardError());
    emit(outputLineChanged());
}

void ShellInvoker::write(QString line){
    QByteArray cmd;
    cmd.append(line).append("\n");
    innerProcess->write(cmd);
}
